// function MethodDecorator(
//     target: Object,      // 类的原型对象（静态方法时是构造函数）
//     propertyKey: string | symbol,  // 方法名
//     descriptor: PropertyDescriptor  // 方法描述符
// ) {
//     // 可以修改 descriptor.value（原方法）实现增强
// }

// 你看到的这个输出结构：
// {
//     kind: 'method',
//         name: 'getName',
//     static: false,
//     private: false,
//     access: { has: [Function], get: [Function] },
//     metadata: undefined,
//         addInitializer: [Function]
// }
// 这正是 ECMAScript 装饰器提案 Stage 3 的标准格式，不再是原来的 target, propertyKey, descriptor 三个参数！


// const MethodDecorator = (
//     value: (this: Person, ...args: any[]) => any,
//     context: ClassMethodDecoratorContext
// ) => {
//     console.log(value)
//     console.log(context)
//     // 返回新函数，替代原方法
//     return function (this: Person, ...args: any[]) {
//         console.log("调用前");
//         const result = value.apply(this, args); // 调用原方法
//         console.log("调用后");
//         return result + "（已装饰）";
//     };
// }

// 装饰器工厂传递参数
// function MethodDecorator(param: string) {
//     return function (
//         value: any,
//         context: ClassMethodDecoratorContext
//     ): any {
//         console.log("param:", param);
//         console.log("原函数:", value);
//         console.log("context:", context);
//         // 返回新的方法函数
//         return function (this: any, ...args: any[]) {
//             console.log("调用前");
//             const result = value.apply(this, args);
//             console.log("调用后");
//             return result + `（已装饰，参数是${param}）`;
//         };
//     };
// }
//
// class DectorPerson {
//     address: string = "上海";
//
// // @MethodDecorator("我是get")
// //     get getAddress() {
// //         return this.address
// //     }
// //
// //     @MethodDecorator("我是set")
// //     set setAddress(value: string) {
// //         this.address = value
// //     }
// //
// //     @MethodDecorator("我是静态函数")
// //     static getAge() {
// //         return 18;
// //     }
//
//     @MethodDecorator("我是撒大声地")
//     getName() {
//         return "的撒娇大数据";
//     }
// }
//
// const useDectorPerson = new DectorPerson();
// console.log(useDectorPerson.getName())

// 介绍context中access的get/set使用
function AccessorDecorator(param: string) {
    return function (value: any, context: any) {
        if (typeof value !== "function") {
            throw new TypeError("Function expected"); // value 应该是 getter/setter 函数
        }
        console.log("param:", param);
        console.log("原函数:", value);
        console.log("context:", context);

// 暂未实现 编译成js会报错
        return {
            get() {
                console.log("调用前", param);
                const result = context.access.get!(this);
                console.log("调用后");
                return result + "（装饰器增强）";
            },
            set(val: any) {
                console.log("设置前");
                context.access.set!(this, val);
                console.log("设置后");
            }
        };
    }
}

class PersonDe {
    private _address: string = "上海";

    // @ts-ignore
    @AccessorDecorator("我是访问器")
    get address() {
        return this._address;
    }

    // @ts-ignore
    @AccessorDecorator("我是set")
    set address(value: string) {
        this._address = value;
    }
}

const usep = new PersonDe();
usep.address = "北京";
console.log(usep.address)
